package com.jyw.business.ast.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jyw.business.ast.domain.AstInfo;
import com.jyw.business.ast.domain.dto.AstOptionDto;
import com.jyw.business.ast.domain.dto.web.*;
import com.jyw.business.ast.domain.vo.web.*;
import com.jyw.business.ast.mapper.AstInfoMapper;
import com.jyw.business.ast.service.IAstInfoService;
import com.jyw.business.router.IRouterMpCodeService;
import com.jyw.common.constant.Constants;
import com.jyw.common.core.page.BasePage;
import com.jyw.common.event.AstMeteringCompleteEvent;
import com.jyw.common.exception.ServiceException;
import com.jyw.common.exception.ValidationException;
import com.jyw.common.utils.CodeUtils;
import com.jyw.common.utils.DateUtils;
import com.jyw.common.utils.PageUtils;
import com.jyw.common.utils.StringUtils;
import com.jyw.common.utils.bean.BeanUtils;
import com.jyw.system.utils.ConversionUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 资产-资产信息Service业务层处理
 *
 * @author system
 * @date 2023-09-20
 */
@Service
@Slf4j
public class AstInfoServiceImpl extends ServiceImpl<AstInfoMapper, AstInfo> implements IAstInfoService {
    @Resource
    private AstInfoMapper astInfoMapper;

    @Resource
    private IRouterMpCodeService routerMpCodeService;
    /**
     * 资产编号前缀
     */
    private final static String ASSET_NUM_PREFIX = "JYW-A";

    /**
     * 查询资产-资产信息
     *
     * @param id 资产-资产信息主键
     * @return 资产-资产信息
     */
    @Override
    public AstInfo selectAstInfoById(Long id) {
        return astInfoMapper.selectAstInfoById(id);
    }

    /**
     * 查询资产-资产信息列表
     *
     * @param astInfo 资产-资产信息
     * @return 资产-资产信息
     */
    @Override
    public List<AstInfo> selectAstInfoList(AstInfo astInfo) {
        return astInfoMapper.selectAstInfoList(astInfo);
    }

    @Override
    public List<AstInfo> selectPlanAstList() {
        return astInfoMapper.selectPlanAstList();
    }

    /**
     * 新增资产-资产信息
     *
     * @param astInfo 资产-资产信息
     * @return 结果
     */
    @Override
    public int insertAstInfo(AstInfo astInfo) {
        astInfo.setCreateTime(DateUtils.getNowDate());
        return astInfoMapper.insertAstInfo(astInfo);
    }

    /**
     * 修改资产-资产信息
     *
     * @param astInfo 资产-资产信息
     * @return 结果
     */
    @Override
    public int updateAstInfo(AstInfo astInfo) {
        astInfo.setUpdateTime(DateUtils.getNowDate());
        return astInfoMapper.updateAstInfo(astInfo);
    }

    /**
     * 批量删除资产-资产信息
     *
     * @param ids 需要删除的资产-资产信息主键
     * @return 结果
     */
    @Override
    public int deleteAstInfoByIds(Long[] ids) {
        return astInfoMapper.deleteAstInfoByIds(ids);
    }

    /**
     * 删除资产-资产信息信息
     *
     * @param id 资产-资产信息主键
     * @return 结果
     */
    @Override
    public int deleteAstInfoById(Long id) {
        return astInfoMapper.deleteAstInfoById(id);
    }

    @Override
    public void add(AstAddDto addDto) {
        AstInfo astInfo = addDto.buildAstInfo();
        if (StringUtils.isEmpty(astInfo.getAssetsCode())) {
            //如果资产编号为空那么需要 系统分配
            astInfo.setAssetsCode(generateAssetCode());
        }
        astInfo.setCreateTime(DateUtils.getNowDate());
        save(astInfo);
    }

    @Override
    public List<AstPageVo> signPage(BasePage page, AstPageDto dto) {
        //如果分页不为空那么,开启分页
        if (!ObjectUtils.isEmpty(page)) {
            PageUtils.startPage();
        }
        List<AstPageVo> list = astInfoMapper.signPage(dto);
        return ConversionUtil.conversionList(list, AstPageVo.class);
    }

    @Override
    public AstDetailVo detail(Long id) {
        AstDetailVo detailVo = new AstDetailVo();

        AstInfo info = getById(id);
        if (ObjectUtils.isEmpty(info)) {
            throw new ValidationException("资产不存在");
        }
        AstInfoDetailVo vo = new AstInfoDetailVo(info);
        if (!ObjectUtils.isEmpty(vo.getPertainUnit())) {
            //通过巡检单元id获取巡检单元名称
            vo.setPertainUnitName(astInfoMapper.getPertainUnitName(vo.getPertainUnit()));
        }
        //设置资产信息
        detailVo.setAstInfo(ConversionUtil.conversion(vo, AstInfoDetailVo.class));
        //查询报修信息
        detailVo.setAstFault(ConversionUtil.conversionList(astInfoMapper.selectOrderFault(id), AstOrderFaultVo.class));
        //查询巡检信息
        detailVo.setInsRecord(ConversionUtil.conversionList(astInfoMapper.selectAstIns(id), AstInsVo.class));
        //查询转移信息
        detailVo.setTransferRecord(ConversionUtil.conversionList(astInfoMapper.selectAstTransfer(id),AstTransferVo.class));
        //查询调拨信息
        detailVo.setAllocateRecord(ConversionUtil.conversionList(astInfoMapper.selectAstAllocate(id),AstAllocateVo.class));
        //查询借用信息
        detailVo.setBorrowRecord(ConversionUtil.conversionList(astInfoMapper.selectAstBorrow(id),AstBorrowVo.class));
        return detailVo;
    }

    @Override
    public void edit(AstEditDto editDto) {
        AstInfo info = editDto.buildAstInfo();
        info.setUpdateTime(DateUtils.getNowDate());
        updateById(info);
        if(ObjectUtils.isEmpty(info.getUseOverDate())||ObjectUtils.isEmpty(info.getNextMeteringDate())){
            LambdaUpdateChainWrapper<AstInfo> wrapper = lambdaUpdate().eq(AstInfo::getId, info.getId());
            if(ObjectUtils.isEmpty(info.getUseOverDate())){
                wrapper.set(AstInfo::getUseOverDate,null);
            }
            if(ObjectUtils.isEmpty(info.getNextMeteringDate())){
                wrapper.set(AstInfo::getNextMeteringDate,null);
            }
            wrapper.update();
        }
    }

    @Override
    public void remove(Long[] ids) {
        lambdaUpdate().in(AstInfo::getId, ids).set(AstInfo::getState, Constants.BOOL_FALSE).set(AstInfo::getPertainUnit, null).update();
    }

    @Override
    public void batchAdd(AstBatchAddDto addDto) {
        String[] seriesNumbArray = addDto.getSeriesNumb().split(",");
        for (Integer i = 0; i < addDto.getSignCount(); i++) {
            //初始化S/N码
            String seriesNumb = "-";
            if (seriesNumbArray.length - 1 > i) {
                //获取S/N码
                seriesNumb = seriesNumbArray[i];
            }
            AstAddDto dto = addDto.buildDto(seriesNumb);
            //调用资产登记方法
            add(dto);
        }
    }

    @Override
    public List<InsUnitAstPageVO> pageUnitAstList(InsUnitAstPageDto insUnitAstPageDto) {
        List<InsUnitAstPageVO> list = astInfoMapper.pageUnitAstList(insUnitAstPageDto);
        return ConversionUtil.conversionList(list, InsUnitAstPageVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void dispose(AstExpireDisposeDto dto) {
        AstInfo info = dto.buildInfo();
        updateById(info);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importData(MultipartFile file) {
        try {
            //读取Excel
            List<AstInfoImportDto> list = EasyExcel
                    //文件流读取
                    .read(file.getInputStream())
                    //指向对象
                    .head(AstInfoImportDto.class)
                    //指定从多少行开始读取
                    .headRowNumber(3)
                    //指定sheet
                    .sheet()
                    //同步读取
                    .doReadSync();
            log.info("资产导入,解析的数据是:{}",list);
            List<AstInfo> collect = list.stream()
                    .map(data -> data.buildInfo())
                    .filter(data ->
                            !(
                                    ObjectUtils.isEmpty(data.getName()) ||
                                            ObjectUtils.isEmpty(data.getAssetsType()) ||
                                            ObjectUtils.isEmpty(data.getAssetsSource())
                            )
                    ).collect(Collectors.toList());
            //保存数据
            saveBatch(collect);
        } catch (Exception e) {
            log.error("资产导入报错",e);
            throw new ServiceException("解析导入模板失败");
        }
    }

    @EventListener({AstMeteringCompleteEvent.class})
    public void meteringComplete(AstMeteringCompleteEvent event){
        log.info("监听到资产保养完成事件:{}",event);
        AstInfo astInfo = getById(event.getId());
        //设置下次保养时间
        updateById(new AstInfo(){{setId(event.getId());setNextMeteringDate(DateUtils.calcAstDate(DateUtils.getNowDate(), BigDecimal.valueOf(astInfo.getMeteringTimer()), astInfo.getMeteringUnit()));}});
    }


    /**
     * 生成资产编号
     *
     * @return
     */
    @Override
    public String generateAssetCode() {
        //查询最大的工单号是多少
        Long maxCode = astInfoMapper.selectMaxNum();
        String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        if (org.springframework.util.StringUtils.isEmpty(maxCode)) {
            return String.format("%s%s%s", ASSET_NUM_PREFIX, today, CodeUtils.autoGenericCode("0", 5));
        } else {
            //取日期是否一致
            if (!today.equals(maxCode.toString().substring(0, 8))) {
                //不一致从1开始
                return String.format("%s%s%s", ASSET_NUM_PREFIX, today, CodeUtils.autoGenericCode("0", 5));
            } else {
                //如果一致取后面编号数
                String code = maxCode.toString().substring(8);
                return String.format("%s%s%s", ASSET_NUM_PREFIX, today, CodeUtils.autoGenericCode(code.toString(), (Integer.valueOf(code) + 1) <= 99999 ? 5 : code.toString().length()));
            }
        }
    }

    @Override
    public Long findInsUnitByName(String name) {
        return astInfoMapper.findInsUnitByName(name);
    }

    @Override
    public List<AstPageVo> option(AstOptionDto dto) {
        List<AstPageVo> option = astInfoMapper.option(dto);
        return ConversionUtil.conversionList(option, AstPageVo.class);
    }

    @Override
    public List<AstInfoExportVo> export(AstPageDto dto) {
        List<AstInfoExportVo> list = astInfoMapper.exportList(dto);
        return ConversionUtil.conversionList(list, AstInfoExportVo.class);
    }

    @Override
    public List<AstPrintVo> print(Long[] ids) {
        List<AstInfo> list = listByIds(Arrays.asList(ids));
        return list.stream().map(data -> {
            AstPrintVo astPrintVo = new AstPrintVo();
            BeanUtils.copyProperties(data, astPrintVo);
            //获取小程序码(业务类型,业务标识,跳转页面)
            String code = routerMpCodeService.createMpCode("ast",data.getId().toString(),"pages/transfer/transfer");
            astPrintVo.setQrCode(code);
            return ConversionUtil.conversion(astPrintVo, AstPrintVo.class);
        }).collect(Collectors.toList());
    }
}
